#include <iostream>
using std::cout;
using std::endl;

class Data
{
public:
    Data(){
        cout << "Data()" << endl;
    }
    ~Data(){
        cout << "~Data()" << endl;
    }

    int getData() const{ return _data; }
private:
    int _data = 10;
};

class MiddleLayer
{
public:
    MiddleLayer(Data * p)
    : _pdata(p)
    {
        cout << "MiddleLayer()" << endl;
    }

    ~MiddleLayer(){
        cout << "~MiddleLayer()" << endl;
        if(_pdata){
            delete _pdata;
            _pdata = nullptr;
        }
    }

    Data * operator->(){
        return _pdata;
    }


    Data & operator*(){
        return *_pdata;
    }
    friend class ThirdLayer;
private:
    Data * _pdata;
};

class ThirdLayer
{
public:
    ThirdLayer(MiddleLayer * ml)
    : _pml(ml)
    {
        cout << "ThirdLayer()" << endl;
    }

    ~ThirdLayer(){
        cout << "~ThirdLayer()" << endl;
        if(_pml){
            delete _pml;
            _pml = nullptr;
        }
    }

    MiddleLayer & operator->(){
        return *_pml;
    }

    //1.一步一步解引用
    /* MiddleLayer & operator*(){ */
    /*     return *_pml; */
    /* } */

    //2.一步到位解引用
    Data & operator*(){
        //从ThirdLayer类得到MiddleLayer对象
        //由于MiddleLayer对解引用运算符进行过重载
        //所以可以直接对MiddleLayer对象解引用，得到Data对象
        /* return *(*_pml); */
        /* return (*_pml).operator*(); */
        return *((*_pml)._pdata);
    }
private:
    MiddleLayer * _pml;
};


void test2(){
    ThirdLayer tl(new MiddleLayer(new Data()));


    //tl调用operator->函数，返回值是其管理的MiddleLayer对象
    //由于MiddleLayer类中已经对->运算符进行了重载
    //所以MiddleLayer对象可以直接使用->运算符访问Data类的成员
    //本质上是调用了MiddleLayer的operator->函数
    cout << ((tl.operator->()).operator->())->getData() << endl;
    cout << (tl.operator->())->getData() << endl;
    cout << tl->getData() << endl;



    //1.一步一步解引用
    //因为MiddleLayer类已经对*运算符进行了重载
    //所以对ThirdLayer对象解引用只需要得到一个MiddleLayer对象
    /* cout << ((tl.operator*()).operator*()).getData() << endl; */
    /* cout << (*(tl.operator*())).getData() << endl; */
    /* cout << (*(*tl)).getData() << endl; */

    //2.一步到位解引用
    cout << (*tl).getData() << endl;
    /* cout << (tl.operator*()).getData() << endl; */
}


void test0(){
    //不建议这样使用，
    //因为如果手动地通过p1指针回收堆上的Data对象
    //会有double free的问题
    Data * p1 = new Data();
    cout << p1->getData() << endl;
    cout << (*p1).getData() << endl;

    MiddleLayer ml(p1);
    /* delete p1; */
}


void test1(){
    Data * p1 = new Data();
    cout << p1->getData() << endl;
    cout << (*p1).getData() << endl;
    delete p1;


    //智能指针的雏形
    //利用局部对象的生命周期管理堆上的资源
    //ml是MiddleLayer类对象，不是指针
    //但是可以像原生的Data*指针一样
    //使用箭头运算符、解引用运算符访问Data的成员
    //并且，不需要像原生的指针一样去手动回收堆上的Data
    MiddleLayer ml(new Data());

    cout << ml->getData() << endl;
    //如下是MiddleLayer使用箭头运算符访问Data类的成员函数的本质形式
    //ml对象调用operator->函数，返回值是一个Data*
    //编译器自动加上一个->(原生的箭头运算符)
    /* cout << ml.operator->()->getData() << endl; */

    cout << (*ml).getData() << endl;
    /* cout << ml.operator*().getData() << endl;//本质 */

}


int main(void){
    test2();
    return 0;
}
